package com.scs.application.modules.wm.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.core.consts.ErrorCode;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.exception.ValidException;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.BeanUtils;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.UtilJava8;
import com.scs.application.modules.base.entity.*;
import com.scs.application.modules.base.enums.ExcelImportBaseDataConfig;
import com.scs.application.modules.base.mapper.LocationLimitMatrMapper;
import com.scs.application.modules.base.mapper.MatrMapper;
import com.scs.application.modules.base.mapper.WarehouseMapper;
import com.scs.application.modules.base.service.LocationService;
import com.scs.application.modules.base.service.MatrUnitService;
import com.scs.application.modules.base.util.SingleService;
import com.scs.application.modules.cfg.utils.ParameterUtils;
import com.scs.application.modules.dept.entity.OprtUse;
import com.scs.application.modules.dept.entity.UseDtl;
import com.scs.application.modules.dept.mapper.OprtUseMapper;
import com.scs.application.modules.dept.mapper.UseDtlMapper;
import com.scs.application.modules.sys.entity.Log;
import com.scs.application.modules.sys.enums.BusType;
import com.scs.application.modules.sys.enums.LogType;
import com.scs.application.modules.sys.model.RestResult;
import com.scs.application.modules.sys.service.LogService;
import com.scs.application.modules.thirdparty.dto.his.HisHighQueryResult;
import com.scs.application.modules.thirdparty.request.convert.his.zhonglian.dto.HisStockQueryZhongLian;
import com.scs.application.modules.thirdparty.request.convert.his.zhonglian.dto.HisStockResultZhongLian;
import com.scs.application.modules.thirdparty.request.view.his.HisReqServiceImpl;
import com.scs.application.modules.wm.dto.*;
import com.scs.application.modules.wm.entity.*;
import com.scs.application.modules.wm.enums.LockBusType;
import com.scs.application.modules.wm.enums.StockLockType;
import com.scs.application.modules.wm.enums.UniqueCodeType;
import com.scs.application.modules.wm.mapper.StockCheckMapper;
import com.scs.application.modules.wm.mapper.StockLockMapper;
import com.scs.application.modules.wm.mapper.StockMapper;
import com.scs.application.modules.wm.mapper.WorkOrderItemMapper;
import com.scs.application.modules.wm.service.InOrderService;
import com.scs.application.modules.wm.service.StockHistoryService;
import com.scs.application.modules.wm.service.StockService;
import com.scs.application.modules.wm.service.StockZeroService;
import com.scs.application.modules.wm.utils.UniqueCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 库存 服务实现类
 * </p>
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class StockServiceImpl extends BaseServiceImpl<StockMapper, Stock> implements StockService {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    @Lazy
    MatrUnitService matrUnitService;

    @Autowired
    @Lazy
    private MatrMapper matrMapper;

    @Autowired
    @Lazy
    private LogService logService;


    @Autowired
    @Lazy
    StockLockMapper stockLockMapper;

    @Autowired
    @Lazy
    StockHistoryService stockHistoryService;
    @Autowired
    @Lazy
    LocationLimitMatrMapper locationLimitMatrMapper;
    @Autowired
    @Lazy
    private LocationService locationService;

    @Autowired
    @Lazy
    WarehouseMapper warehouseMapper;

    @Autowired
    @Lazy
    private StockCheckMapper stockCheckMapper;


    @Autowired
    @Lazy
    StockZeroService stockZeroService;
    @Autowired
    @Lazy
    HisReqServiceImpl hisReqServiceImpl;
    @Resource
    @Lazy
    private UseDtlMapper useDtlMapper;
    @Resource
    private WorkOrderItemMapper workOrderItemMapper;
    @Resource
    private OprtUseMapper oprtUseMapper;

    @Override
    public Double getAvailableStock(String warehouseId, String materialId, StockLockType lockType) {
        if (lockType == StockLockType.VIRTUAL) {
            return baseMapper.getAvailableStockVirtual(warehouseId, materialId);
        } else if (lockType == StockLockType.BY_LOT) {
            return baseMapper.getAvailableStockLot(warehouseId, materialId);
        } else {
            throw new BusinessException("unique_code模式的暂不提供查询");
        }
    }

    @Override
    public List<Stock> getAvailableStockList(String warehouseId, String materialId, String lot) {
        return baseMapper.getFreeStockLot(warehouseId, materialId, lot);
    }

    @Override
    public String splitStock(Stock stock, Double qty) {
        Stock newStock = new Stock();
        if (stock.getSkuQty() < qty) {
            throw new BusinessException("分拆数量大于库存数量！");
        }
        BeanUtils.copyProperties(stock, newStock);
        stock.setSkuQty(stock.getSkuQty() - qty);
        stock.setAmount(stock.getSkuQty() * stock.getSkuPrice());
        stock.setPackageUnit(stock.getSkuUnit());
        stock.setPackageQty(stock.getSkuQty());
        newStock.setSkuQty(qty);
        newStock.setAmount(newStock.getSkuPrice() * qty);
        newStock.setPackageQty(qty);
        newStock.setPackageUnit(newStock.getSkuUnit());
        newStock.setId(null);
        this.updateById(stock);
        this.save(newStock);
        return newStock.getId();
    }

    @Override
    public void mergeStock(String stockId) {
        Stock stock = this.getById(stockId);
        if (stock == null) {
            throw new BusinessException("未找到库存记录！");
        }
        mergeStock(stock);
    }

    /**
     * @param stock
     */
    @Override
    public void mergeStock(Stock stock) {
        if (stock.getFlagUniqueCode()) {
            throw new BusinessException("一物一码管理的库存不能合并!");
        }
        List<Stock> targetStockList = this.list(new QueryWrapper<Stock>()
                .eq("warehouse_id", stock.getWarehouseId())
                .eq("location_id", stock.getLocationId())
                .eq("line_id", stock.getLineId())
                .eq("package_unit", stock.getPackageUnit())
                .eq("flag_unique_code", 0)
                .ne("id", stock.getId())
                .orderByDesc("sku_qty"));
        if (targetStockList.size() > 0) {
            Stock targetStock = targetStockList.get(0);
            targetStock.setPackageQty(targetStock.getPackageQty() + stock.getPackageQty());
            targetStock.setSkuQty(targetStock.getSkuQty() + stock.getSkuQty());
            targetStock.setAmount(targetStock.getSkuQty() * targetStock.getSkuPrice());
            this.updateById(targetStock);
            this.removeById(stock.getId());
        }
    }

    @Override
    public List<Stock> pack(String stockId, String unit, Integer packQty, String serialRuleCode) {
        List<Stock> packStocks = new ArrayList<>();
        Stock stock = this.getById(stockId);
        if (stock == null) {
            throw new BusinessException("未找到库存记录！");
        }
        MatrUnit matrUnit = matrUnitService.getOne(new QueryWrapper<MatrUnit>()
                .eq("matr_id", stock.getMatrId())
                .eq("unit", unit));
        if (matrUnit == null) {
            throw new BusinessException("物料未配置此单位：" + unit);
        }
        if (matrUnit.getRate() * packQty > stock.getSkuQty()) {
            throw new BusinessException("加工数量不足！");
        }
        _unpack(stock);
        for (Integer i = 0; i < packQty; i += 1) {
            Stock packStock = new Stock();
            BeanUtils.copyProperties(stock, packStock);
            packStock.setId(null);
            packStock.setSn(serialRuleAdapter.getSerialRuleService().generateCode(serialRuleCode));
            packStock.setPackageQty(1.0);
            packStock.setPackageUnit(unit);
            packStock.setFlagUniqueCode(true);
            packStock.setSkuQty(Double.parseDouble(matrUnit.getRate().toString()));
            packStock.setAmount(packStock.getSkuPrice() * packStock.getSkuQty());
            packStock.setInTime(null);
            this.save(packStock);
            packStocks.add(packStock);
        }
        stock.setSkuQty(stock.getSkuQty() - packQty * matrUnit.getRate());
        stock.setPackageQty(stock.getSkuQty());
        stock.setPackageUnit(stock.getSkuUnit());
        stock.setAmount(stock.getSkuQty() * stock.getSkuPrice());
        this.updateById(stock);

        return packStocks;
    }

    @Override
    public void unpack(String stockId) {
        Stock stock = this.getById(stockId);
        if (stock == null) {
            throw new BusinessException("未找到库存记录！");
        }
        _unpack(stock);
        mergeStock(stockId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public HisStockDTO queryByUniqueCode(String uniqueCode) {
        if (StringUtils.isBlank(uniqueCode)) {
            throw new BusinessException("唯一码不能为空");
        }
        QueryWrapper<Stock> wrapper = getStockQueryWrapper(uniqueCode);

        HisStockDTO dto = this.baseMapper.getStockByUniqueCode(wrapper);

        if (dto == null) {
            throw new BusinessException("唯一码【%s】未在库存中找到",uniqueCode);
        }
        if (dto.getPackageQty() == 0) {
            throw new BusinessException("唯一码【%s】库存为 0",uniqueCode);
        }
        if (dto.getLockQty() != null) {
//            throw new BusinessException("该唯一码已被锁定");
        }
        if (dto.getFlagDisabled()) {
            throw new BusinessException("唯一码【%s】所关联的耗材已禁用",uniqueCode);
        }
        if (dto.getHisDisabled()) {
            throw new BusinessException("唯一码【%s】所关联的耗材his已禁用",uniqueCode);
        }
        if (StringUtils.isBlank(dto.getMscmCode())) {
//            throw new BusinessException("该唯一码所关联耗材尚未同步首营平台");
        }
        if (DateUtils.compareDate(dto.getExpDate(), new Date())) {
            throw new BusinessException("该SN【%s】效期【%s】已过期", uniqueCode, DateUtils.format(dto.getExpDate()));
        }
        dto.setAction("queryByUniqueCode").setActionTime(DateUtils.nowDate());

        List<StockLock> locks = stockLockMapper.selectList(Wrappers.<StockLock>query().eq("stock_id", dto.getStockId()));
        if (locks != null && locks.size() > 0){
            BusinessException.throwError("唯一码无法使用，已被锁定: %s",locks.get(0).getLockComment());
        }
        return dto;
    }

    @Override
    public HisHighQueryResult queryByUniqueCodeFoHis(String uniqueCode) {
        QueryWrapper<Stock> wrapper = getStockQueryWrapper(uniqueCode);
        HisStockDTO dto = this.baseMapper.getStockByUniqueCode(wrapper);
        if (dto == null) {
            throw new ValidException("唯一码【%s】未在库存中找到",uniqueCode);
        }
        if (dto.getPackageQty() == 0) {
            throw new ValidException("唯一码【%s】库存为 0",uniqueCode);
        }
        if (dto.getFlagDisabled()) {
            throw new ValidException("唯一码【%s】所关联的耗材已禁用",uniqueCode);
        }
        if (dto.getHisDisabled()) {
            throw new ValidException("唯一码【%s】所关联的耗材his已禁用",uniqueCode);
        }
        if (!dto.getFlagOmoc()) {
            throw new ValidException("唯一码【%s】不是标签管理耗材",uniqueCode);
        }
        if (DateUtils.compareDate(dto.getExpDate(), new Date())) {
            throw new ValidException("唯一码【%s】效期【%s】已过期", uniqueCode, DateUtils.format(dto.getExpDate()));
        }
        List<StockLock> locks = stockLockMapper.selectList(Wrappers.<StockLock>query().eq("stock_id", dto.getStockId()));
        if (locks != null && locks.size() > 0){
            BusinessException.throwValidFail("唯一码无法使用，已被锁定: %s",locks.get(0).getLockComment());
        }
        HisHighQueryResult result = new HisHighQueryResult();
        org.springframework.beans.BeanUtils.copyProperties(dto, result);
        result.setMatrCode(dto.getHrpCode());
        return result;
    }

    @Override
    public QueryWrapper getStockQueryWrapper(String uniqueCode) {
        // 判断唯一码类型
        UniqueCodeType uniqueCodeType = UniqueCodeUtils.getUniqueCodeType(uniqueCode);
        QueryWrapper wrapper = new QueryWrapper<>();

        if (uniqueCodeType == UniqueCodeType.SN) {
            wrapper.eq("sn", uniqueCode);
            this.haveSn(uniqueCode);
        } else if (uniqueCodeType == UniqueCodeType.RFID) {
            wrapper.eq("rfid", uniqueCode);
        } else if (uniqueCodeType == UniqueCodeType.UDI) {
            wrapper.eq("udi", uniqueCode);
        }
        return wrapper;
    }

    @Override
    public Stock getStockByUC(String uc, String ucType, String warehouseId) {
        Stock stock = baseMapper.selectOne(Wrappers.<Stock>query()
                .eq("warehouse_id", warehouseId)
                .eq(ucType, uc));
        if (stock == null) {
            throw new BusinessException("唯一码未在指定的仓库中找到！");
        }
        return stock;
    }

    @Override
    public Map getProcessInfoByUC(String uc, String ucType, String warehouseId) {

        Stock stock = baseMapper.selectOne(Wrappers.<Stock>query()
                .eq(ucType, uc)
                .gt("sku_qty", 0)
                .eq("warehouse_id", warehouseId)
                .last("limit 1"));
        if (stock == null) {
            throw new BusinessException("此唯一码在此库房没有找到，请检查！");
        }
        StockLock stockLock = stockLockMapper.selectOne(Wrappers.<StockLock>query()
                .eq("stock_id", stock.getId()));
        if (stockLock != null) {
            throw new BusinessException("此库存已被锁定，不能进行加工!,锁定信息：" + stockLock.getLockComment());
        }
        Double rate = stock.getSkuQty() / stock.getPackageQty();
        QueryWrapper<MatrUnit> wrapper = new QueryWrapper<MatrUnit>()
                .eq("matr_id", stock.getMatrId())
                .ne("unit", stock.getSkuUnit())
                .lt("rate", rate)
                .orderByDesc("rate");
        List<MatrUnit> options = matrUnitService.list(wrapper);
        if (options.size() == 0) {
            throw new BusinessException("此物料未能检索到合适的加工单位，请检查耗材的单位配置！");
        }
        Map map = new HashMap();
        map.put("stock", stock);
        map.put("options", options);
        return map;
    }

    @Override
    public Map getProcessInfoByWoId(String workOrderId) {
        List<MatrUnit> options = new ArrayList<>();
        List<Stock> stocks = baseMapper.getStockByWoId(workOrderId);
        for (Stock stock : stocks) {
            QueryWrapper<MatrUnit> wrapper = new QueryWrapper<MatrUnit>()
                    .eq("matr_id", stock.getMatrId())
                    .ne("unit", stock.getSkuUnit())
                    .orderByDesc("rate");
            List<MatrUnit> stockOptions = matrUnitService.list(wrapper);
            options.addAll(stockOptions);
        }
        Map map = new HashMap();
        map.put("stocks", stocks);
        map.put("options", options);
        return map;
    }

    @Override
    public void racking(RackingDTO rackingDTO) {
        List<Stock> rackingItems = rackingDTO.getRackingItems();
        for (Stock stock : rackingItems) {
            stock.setLocationId(rackingDTO.getLocationId());
        }
        this.updateBatchById(rackingItems);
    }

    private void _unpack(Stock stock) {
        this.update(Wrappers.<Stock>update().eq("id", stock.getId())
                .set("flag_unique_code", 0)
                .set("sn", null)
                .set("rfid", null)
                .set("udi", null)
                .set("package_unit", stock.getSkuUnit())
                .set("package_qty", stock.getSkuQty())
        );
    }

    @Override
    public List<Stock> getStockByLineId(String lineId) {

        List<Stock> stockList = list(Wrappers.<Stock>query().eq("line_id", lineId));
        if (stockList.size() == 0) {
            throw new BusinessException("未通过审核，请审核通过后再进行加工!");
        }
        return stockList;
    }


    @Override
    public void bindingRFID(String sn, String rfid) {
        update(Wrappers.<Stock>update()
                .eq("sn", sn)
                .set("rfid", rfid));
    }

    @Override
    public List<StockDTO> getStockWarning() {
        return this.baseMapper.getStockWarning();
    }

    @Override
    public List<StockDTO> getStockDate() {
        return this.baseMapper.getStockDate();
    }

    @Override
    public List<Stock> getStockExpDate() {
        return this.baseMapper.getStockExpDate();
    }

    @Override
    public IPage pageForUse(QueryContext queryContext) {
        QueryWrapper wrapper = queryContext.getWrapper();
        wrapper.gt("package_qty", 0);
        wrapper.eq("lock_qty", 0);
        return this.baseMapper.page(queryContext.getPage(), wrapper, queryContext.getParams());
    }

    @Override
    public IPage pageForRedType(QueryContext queryContext) {
        QueryWrapper wrapper = queryContext.getWrapper();
        wrapper.eq("package_qty", 0);
        wrapper.eq("lock_qty", 0);
        return this.baseMapper.page(queryContext.getPage(), wrapper, queryContext.getParams());
    }


    @Override
    public void rfidBindOrUnbind(String sn, String rfid, String opType) {
        Stock stock = this.getStockByUniqueCode(sn);
        if (stock == null) {
            throw new BusinessException(String.format("在库存中未找到%s相关的耗材", sn));
        }
        if (stock.getSkuQty() <= 0) {
            throw new BusinessException("无库存");
        }
        // 判断是否已经锁定过
        StockLock stockLock = stockLockMapper.selectOne(new QueryWrapper<StockLock>().eq("stock_id", stock.getId()));

        if (stockLock != null) {
            throw new BusinessException("已存在锁定记录");
        }

        if (opType.equals("bind")) {//绑定
            Stock stockRfid = this.getStockByUniqueCode(rfid);
            if (stockRfid != null && !stockRfid.getMatrId().equals(stock.getMatrId())) {
                throw new BusinessException("RFID已被【" + stockRfid.getSn() + "】绑定");
            }
            if (!StringUtils.isBlank(stock.getRfid()) && !stock.getRfid().equals(rfid))
                throw new BusinessException("SN【" + stock.getSn() + "】已绑定RFID【" + stock.getRfid() + "】，若需重新绑定，请先解绑");

        } else {//解绑
            if (StringUtils.isBlank(stock.getRfid()))
                throw new BusinessException("SN【" + stock.getSn() + "】未绑定RFID，无法解绑");
        }
        //更新入库单类型
        this.update(Wrappers.<Stock>update().eq("id", stock.getId())
                .set("rfid", rfid)
        );
    }

    @Override
    public List<StockDTO> dtoList(QueryWrapper<Stock> wrapper) {
        return baseMapper.list(wrapper);
    }
    @Override
    public Stock getStockByUC(String uc) {
        Stock stock = this.getExpStockByUC(uc);
        if (stock == null) {
            throw new BusinessException("唯一码【" + uc + "】未找到库存记录！");
        }
        if (stock.getSkuQty() <= 0) {
            throw new BusinessException("唯一码【" + uc + "】库存数量为0！");
        }
        return stock;
    }

    @Override
    public Stock getStockByUniqueCode(String uniqueCode) {
        if (StringUtils.isBlank(uniqueCode)) {
            throw new BusinessException("唯一码不能为空");
        }

        // 判断唯一码类型
        QueryWrapper wrapper = getStockQueryWrapper(uniqueCode);
        wrapper.last("limit 1");
        Stock stock = this.getOne(wrapper);
        if (stock == null) {//查找0库存
            StockZero stockZero = stockZeroService.getOne(wrapper);
            if (stockZero != null) {
                stock = new Stock();
                BeanUtils.copyProperties(stockZero,stock);
            }
        }

        if (stock == null) {
            return stock;
        }

        StockLock stockLock = stockLockMapper.selectOne(new QueryWrapper<StockLock>().eq("stock_id", stock.getId()));
        if (stockLock != null) {
            stock.setLockId(stockLock.getId());
            String lockInfo = stockLock.getLockComment();
            // 消耗计费 SN001已被病人名称使用（消耗单号：20220001）
            if (LockBusType.OPRT_USE.name().equals(stockLock.getBusType()) && StringUtils.isNotBlank(stockLock.getBusKeyValue())) {
                OprtUse oprtUse = oprtUseMapper.selectById(stockLock.getBusKeyValue());
                if (oprtUse != null) {
                    if (StringUtils.isNotBlank(oprtUse.getPatientName())) {
                        lockInfo = StrUtil.format("{}已被病人{}使用, 消耗单{}, 消耗日期{}",stock.getSn(),oprtUse.getPatientName(),oprtUse.getBusKey(),DateUtils.format(oprtUse.getBusDate(),DateUtils.DATE_PATTERN));
                    } else {
                        lockInfo = StrUtil.format("{}已被使用, 消耗单{}, 消耗日期{}",stock.getSn(),oprtUse.getBusKey(),DateUtils.format(oprtUse.getBusDate(),DateUtils.DATE_PATTERN));
                    }
                }
            }
            stock.setLockInfo(lockInfo);
        }

        return stock;
    }

    @Override
    public Stock getStockByUniqueCodeWithBusKeyValue(String uniqueCode, String busKeyValue) {
        if (StringUtils.isBlank(uniqueCode)) {
            throw new BusinessException("唯一码不能为空");
        }

        // 判断唯一码类型
        QueryWrapper wrapper = getStockQueryWrapper(uniqueCode);
        wrapper.last("limit 1");
        Stock stock = this.getOne(wrapper);
        if (stock == null) {//查找0库存
            StockZero stockZero = stockZeroService.getOne(wrapper);
            if (stockZero != null) {
                stock = new Stock();
                BeanUtils.copyProperties(stockZero,stock);
            }
        }

        if (stock == null) {
            return stock;
        }

        StockLock stockLock = stockLockMapper.selectOne(new QueryWrapper<StockLock>().eq("stock_id", stock.getId()).eq("bus_key_value", busKeyValue));
        if (stockLock != null) {
            stock.setLockId(stockLock.getId());
            String lockInfo = stockLock.getLockComment();
            // 消耗计费 SN001已被病人名称使用（消耗单号：20220001）
            if (LockBusType.OPRT_USE.name().equals(stockLock.getBusType()) && StringUtils.isNotBlank(stockLock.getBusKeyValue())) {
                OprtUse oprtUse = oprtUseMapper.selectById(stockLock.getBusKeyValue());
                if (oprtUse != null) {
                    if (StringUtils.isNotBlank(oprtUse.getPatientName())) {
                        lockInfo = StrUtil.format("{}已被病人{}使用, 消耗单{}, 消耗日期{}",stock.getSn(),oprtUse.getPatientName(),oprtUse.getBusKey(),DateUtils.format(oprtUse.getBusDate(),DateUtils.DATE_PATTERN));
                    } else {
                        lockInfo = StrUtil.format("{}已被使用, 消耗单{}, 消耗日期{}",stock.getSn(),oprtUse.getBusKey(),DateUtils.format(oprtUse.getBusDate(),DateUtils.DATE_PATTERN));
                    }
                }
            }
            stock.setLockInfo(lockInfo);
        }

        return stock;
    }

    @Override
    public List<Stock> getStockListByUniqueCode(String uniqueCode) {
        if (StringUtils.isBlank(uniqueCode)) {
            throw new BusinessException("唯一码不能为空");
        }

        // 判断唯一码类型
        QueryWrapper wrapper = getStockQueryWrapper(uniqueCode);

        List<Stock> stockList=this.list(wrapper);

            if (stockList.size()==0) {//查找0库存
                List<StockZero> stockZerolist = stockZeroService.list(wrapper);
            if (stockZerolist.size() != 0) {

                for(StockZero stockZero:stockZerolist ){
                    Stock stock = new Stock();
                    BeanUtils.copyProperties(stockZero,stock);
                    stockList.add(stock);
                }

            }
        }

        return stockList;
    }

    @Override
    public List<Stock> getStockListBySns(List<String> sns, String warehouseId) {
        return this.list(Wrappers.<Stock>query().eq("warehouse_id", warehouseId).in("sn", sns).gt("sku_qty", 0));
    }

    @Override
    public List<Stock> getStockByCode(String uniqueCode) {
        if (StringUtils.isBlank(uniqueCode)) {
            throw new BusinessException("唯一码不能为空");
        }

        // 判断唯一码类型
        QueryWrapper wrapper = getStockQueryWrapper(uniqueCode);

        List<Stock> stockList=this.list(wrapper);

        return stockList;
    }

    @Override
    public Page<Map> pageForDemand(QueryContext context, Map<String, Object> userParam) {
        return this.baseMapper.pageForDemand(context.getPage(), context.getWrapper(), context.getParams(), userParam);
    }


    @Override
    public List<Stock> getTcbstockInsertList() {
        return baseMapper.getTcbstockInsertList();
    }

    /**
     * 库存备份，同一日期只允许一次备份
     */
    @Transactional(isolation = Isolation.SERIALIZABLE)
    @Override
   synchronized public String updateStockHistory() {
        String msg="";
        msg+=this.updateOeAddStockZero();
        //查询当前所有库存记录
        List<Stock> stockList = this.list(Wrappers.<Stock>query().ne("sku_qty", "0"));
        logger.info("共查询到" + stockList.size() + "条数据");
        if (!stockList.isEmpty()) {
            String dateNow = DateUtils.format(new Date(), "yyyy-MM-dd");
            //删除当天存的数据
            stockHistoryService.remove(Wrappers.<StockHistory>query().eq("back_date",dateNow));

            List<StockHistory> stockHistoryList = new ArrayList<>(stockList.size());
            //copy stockList数据到stockHistoryList
            BeanUtils.copyProperties(stockList, stockHistoryList, StockHistory.class);
            stockHistoryList.stream().forEach(o -> o.setBackDate(new Date()).setId(null));
            stockHistoryService.saveBatch(stockHistoryList);
        }

        msg+="库存备份操作，添加数量:"+(stockList != null ? stockList.size() : 0);
        logger.info(msg);
        return msg;
    }

    /**
     * @Description： 更新或者删除0库存
     *<pre>
     *     1、添加 wm_stock sku_qty=0的库存记录到 wm_stock_zero
     *     2、删除 wm_stock sku_qty=0的库存记录
     *</pre>
     */
    @Override
    synchronized  public String updateOeAddStockZero() {
        //查询当前所有库存记录
        int stockListEq0 = this.count(Wrappers.<Stock>query().eq("sku_qty", "0"));
        if (stockListEq0 > 0) {
            // 2、添加 wm_stock sku_qty=0的库存记录到 wm_stock_zero
            List<String> names= new ArrayList<String>();
            names.add("id");
            Arrays.stream(StockZero.class.getDeclaredFields()).forEach(field -> {
                names.add(StringUtils.camelToUnderline(field.getName(),1));
            });
            String namesStr = StringUtils.join(names,",");
            jdbcTemplate.execute(" insert into wm_stock_zero ("+namesStr+") select "+namesStr+" from wm_stock where sku_qty = 0 ");

            //3、删除 wm_stock sku_qty=0的库存记录
            this.remove(Wrappers.<Stock>query().eq("sku_qty", "0"));
        }
        return "<br>零库存操作，添加数量:"+stockListEq0+"<br>";
    }

    @Override
    public Page<Map> pageForStockCheck(QueryContext context, Map<String, Object> userParam) {
        if (userParam == null ) {
            userParam = context.getParams();
        }
        Page<Map> page = this.baseMapper.pageForStockCheck(context.getPage(), context.getWrapper(), userParam);
        return page;
    }


    @Override
    public Page<Map> pageForPrint(QueryContext context) {
        Page<Map> page = this.baseMapper.pageForPrint(context.getPage(), context.getWrapper());
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePrintNum(JSONArray snArr) {
        if (snArr == null || snArr.size() < 1) return;
        List<String> snList = JSONArray.toJavaObject(snArr, List.class);
        List<Stock> stocks = baseMapper.selectList(Wrappers.<Stock>query().in("sn", snList));
        stocks.forEach(stock -> {
            Integer printNum = stock.getPrintNum();
            if (printNum == null) printNum = 0;
            printNum++;
            stock.setPrintTime(DateUtils.now()).setPrintNum(printNum);
            baseMapper.updateById(stock);
        });
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    /**
     * @Description： 上架
     */
    public String upShelves(String uniqueCode) {
        String msg = "上架失败，";
        if (StringUtils.isBlank(uniqueCode)) throw new BusinessException("缺少参数uniqueCode");
        Stock stock = this.getExpStockByUC(uniqueCode);

        MatrUnit matrUnit = matrUnitService.getOne(Wrappers.<MatrUnit>query()
                .eq("matr_id", stock.getMatrId())
                .eq("unit", stock.getPackageUnit()), false);
        if (matrUnit == null) throw new BusinessException(msg + "未找到耗材单位，单位【%s】", stock.getPackageUnit());

        LocationLimitMatr existLocationLimitMatr = locationLimitMatrMapper.selectOne(Wrappers.<LocationLimitMatr>query()
                .eq("matr_id", stock.getMatrId())
                .eq("package_unit", stock.getPackageUnit())
                .eq("warehouse_id", stock.getWarehouseId()));
        if (existLocationLimitMatr == null)
            throw new BusinessException(msg + "未找到该耗材单位的库位耗材设置\n耗材：%s，单位：%s", stock.getMatrName(), stock.getPackageUnit());

        Location location = locationService.getById(existLocationLimitMatr.getLocationId());
        if (location == null)
            throw new BusinessException(msg + "未找到库位，库位代码【%s】", existLocationLimitMatr.getLocationCode());
        if (stock.getLocationId().equals(location.getId()))
            throw new BusinessException(msg + "该库存已在库位【%s】上，无需上架", existLocationLimitMatr.getLocationName());

        stock.setLocationId(location.getId()).setLocationName(location.getName());
        this.updateById(stock);
        msg = String.format("上架成功，仓库：%s，货位：%s(%s)", stock.getWarehouseName(), location.getName(), location.getCode());
        return msg;
    }

    /**
     * @param warehouseId
     * @param locationId
     * @Description： 上架
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult upShelvesBatch(String warehouseId, String locationId) {
        RestResult restResult = RestResult.ok("上架成功");
        //是否进入盘点模式
        if(ParameterUtils.getFlagStockCheck()){
            //有未完成的盘点单则全部锁定
            List<StockCheck> stockChecks = stockCheckMapper.selectList(Wrappers.<StockCheck>query().eq("flag_finished", false));
            if(stockChecks != null && stockChecks.size() > 0) {
                throw new BusinessException("当前处于盘点模式，请在盘点结束后再进行操作！");
            }
        }
        Warehouse warehouse = warehouseMapper.selectById(warehouseId);
        if (warehouse == null) throw new BusinessException("该仓库不存在或者已被移出");

        //1、相关库位
        List<Location> locationList = locationService.list(Wrappers.<Location>query().eq("warehouse_id", warehouse.getId()).eq("type", "shelves"));
        if (locationList == null || locationList.size() < 1)
            throw new BusinessException("未找到相关货架<br>仓库：%s", warehouse.getName());
        List<String> locationIdList = locationList.stream().map(Location::getId).collect(Collectors.toList());

        //2、库位耗材关系
        List<LocationLimitMatr> locationLimitMatrList = locationLimitMatrMapper.selectList(Wrappers.<LocationLimitMatr>query()
                .in("location_id", locationIdList));
        if (locationLimitMatrList == null || locationLimitMatrList.size() < 1)
            throw new BusinessException("相关货架均未设置库位耗材关系<br>仓库：%s", warehouse.getName());

        //3、相关库存
        QueryWrapper queryWrapper = new QueryWrapper<Stock>().eq("warehouse_id", warehouseId).gt("sku_qty", 0);
        List<Stock> stockList = this.list(queryWrapper);
        if (stockList == null || stockList.size() < 1)
            throw new BusinessException("未找到可上架库存<br>仓库：%s", warehouse.getName());

        //分组去重，条件：耗材id，包装单位
        List<Stock> stockGroupList = UtilJava8.stockGroupForUpShelvesBatch(stockList);
        final int[] numStock = {0};
        final int[] numLocation = {0};
        final int[] numNoLocation = {0};
        stockGroupList.stream().forEach(stockGroup -> {
            //符合该分组的所有库存
            List<Stock> stockUndateList = UtilJava8.stockFilterForUpShelvesBatch(stockList, stockGroup);

            //查找对应耗材和包装的库位
            List<LocationLimitMatr> locationLimitMatrFindList = locationLimitMatrList.stream()
                    .filter(
                            stockTmp -> stockTmp.getMatrId().equals(stockGroup.getMatrId()) && stockTmp.getPackageUnit().equals(stockGroup.getPackageUnit())
                    ).collect(Collectors.toList());
            if (locationLimitMatrFindList == null || locationLimitMatrFindList.size() < 1) {
                numNoLocation[0] += stockUndateList.size();
            } else if (locationLimitMatrFindList.size() > 1) {
                throw new BusinessException("该耗材单位设置了%s个库位关系，请检查<br>耗材：%s，单位：%s", locationLimitMatrFindList.size(), stockGroup.getMatrName(), stockGroup.getPackageUnit());
            } else { //只有1条
                numStock[0] += stockUndateList.size();
                numLocation[0] += 1;
                List<String> stockIdList = stockUndateList.stream().map(Stock::getId).collect(Collectors.toList());
                this.update(Wrappers.<Stock>update()
                        .in("id", stockIdList)
                        .set("location_id", locationLimitMatrFindList.get(0).getLocationId())
                        .set("location_name", locationLimitMatrFindList.get(0).getLocationName()));
            }
        });
        restResult.setMsg(String.format("上架成功<br>影响库位：%s，影响库存：%s<br>未匹配到库位库存：%s", numLocation[0], numStock[0], numNoLocation[0]));
        return restResult;
    }

    /*科室退货批量选择*/
    @Override
    public IPage pageDeptReturn(QueryContext queryContext, Map<String, Object> userParam) {
        QueryWrapper wrapper = queryContext.getWrapper();
        return this.baseMapper.pageDeptReturn(queryContext.getPage(), wrapper, userParam);
    }

    /*获取耗材货位*/
    @Override
    public List<Map<String, Object>> getStockByMatr(String matrId) {
        String sql = "select t1.location_id,t1.location_name,t1.package_unit,t1.sn,t2.code as location_code from wm_stock t1 inner join base_location t2 on t1.location_id= t2.id where t1.sku_qty>0 and (t2.type is null or t2.type='shelves')";
        sql += "and t1.matr_id = '" + matrId + "' group by location_id,package_unit";
        List<Map<String, Object>> list= this.jdbcTemplate.queryForList(sql);
        return list;
    }


    @Override
    public Page<Stock> pageForStockDiff(QueryContext context, Map<String, Object> userParam) {
        return this.baseMapper.pageForStockDiff(context.getPage(), context.getWrapper(), context.getParams(), userParam);
    }

    @Override
    public String diffHandle(String type, String stockId) {
        if (!"to0,to1".contains(type)) throw new BusinessException("操作类型错误");
        Stock stock = this.getById(stockId);
        if (stock == null) throw new BusinessException("库存记录不存在");

        if (type.equals("to0")){ //清空库存
            if (stock.getPackageQty() < 1) throw new BusinessException("该库存已没有库存，无需清空");
            StockLock stockLock = stockLockMapper.selectOne(Wrappers.<StockLock>query().eq("stock_id", stock.getId()));
            if (stockLock != null) {
                throw new BusinessException("此库存已被锁定，不能进行清空!,锁定信息：" + stockLock.getLockComment());
            }
            stock.setSkuQty(0d).setAmount(0d).setPackageQty(0d);
        } else { //还原库存
            if (stock.getPackageQty() > 0) throw new BusinessException("该库存已有库存，无需还原");
            MatrUnit matrUnit = matrUnitService.getOne(new QueryWrapper<MatrUnit>()
                    .eq("matr_id", stock.getMatrId())
                    .eq("unit", stock.getPackageUnit()));
            if (matrUnit == null)  throw new BusinessException("未找到库存对应的包装单位【%s】：",stock.getPackageUnit());

            stock.setSkuQty(matrUnit.getRate()).setAmount(matrUnit.getPrice()).setPackageQty(1d);
        }
        this.updateById(stock);
        return type.equals("to0") ? "库存清空成功" : "库存还原成功";
    }



    /**
    * @Description： 查询库存，同时也查询0库存表，一般用于科室退货、供应商退货、his退费、科室冲红等反向添加库存业务
     * @param queryWrapper 查询条件
     * @param userParam     特殊条件，预留(暂未实现)
    */
    @Override
    public List<Stock> listStockWithZero(QueryWrapper queryWrapper,Map<String,Object> userParam) {
        List<Stock> stockList = new ArrayList<>();
        List<Stock> list = this.list(queryWrapper);
        List<StockZero> listZero = stockZeroService.list(queryWrapper);
        if (list != null && list.size() > 0) {
            stockList.addAll(list);
        }
        if (listZero != null && listZero.size() > 0) {
            listZero.forEach(stockZero -> {
                Stock stock = new Stock();
                BeanUtils.copyProperties(stockZero, stock);
                stockList.add(stock);
            });
        }
        return stockList;
    }



    /**
     * @Description： 查询库存，同时也查询0库存表，一般用于科室退货、供应商退货、his退费、科室冲红等反向添加库存业务
     * @param id
     */
    @Override
    public Stock getByIdWithZero(String id) {
        Stock stock = this.getById(id);
        if (stock == null) {//查找0库存
            StockZero stockZero = stockZeroService.getById(id);
            if (stockZero != null) {
                stock = new Stock();
                BeanUtils.copyProperties(stockZero,stock);
            }
        }
        return stock;
    }

    @Override
    public Page<Map> pageStockWithZero(QueryContext context, Map<String, Object> userParam) {
        Page<Map> page = this.baseMapper.pageStockWithZero(context.getPage(), context.getWrapper(), context.getParams(), userParam);
        return page;
    }


    /**
     * 耗材停用
     * @return
     */
    @Override
    public RestResult syncHrpMatrStop(){
        JSONObject logdesc = new JSONObject();
        Log log = Log.getLog(BusType.HrpType.type08, LogType.success, "system", logdesc);
        RestResult restResult=null;
        int StopCount=0;
        String msg="";
        try{
        //判断临采未停用的耗材
        List<Matr> matrHrpCodeList=matrMapper.selectIsTermPurchase();
        for(Matr matr:matrHrpCodeList){
            Stock stock=this.getById(matr);
            //库存不存在则推送
            if(stock!=null){
//                restResult=UtilSOAP.sendHrpMatrCode(matr.getHrpCode());
                //推送至HRP
                StopCount++;
            }
        }
        msg = "操作成功," + "-[syncHrpMatrStop]推送HRP耗材编码---本次推送" + StopCount + "个耗材";
        Date dateNow = new Date();
        restResult.setMsg(msg);
        logger.info("-" + DateUtils.getDate(dateNow) + "--------" + msg + "--------");
        log.setParam(msg);
        }catch(Exception e){
            logger.error("StockServiceImpl.syncHrpMatrStop", e);
            restResult.setCode(ErrorCode.COMMON_ERROR);
            restResult.setMsg("操作失败," + e.getMessage());
            restResult.setSuccess(false);
            log.setLog(LogType.error, e.getMessage());
        } finally {
            logService.save(log);
            return restResult;

        }
    }


    @Override
    public List<StockGroupWarehouseMatrDTO> getListGroupByMatr(QueryWrapper queryWrapper) {
        List<StockGroupWarehouseMatrDTO> stockGroupWarehouseMatrDTOS= this.baseMapper.getListGroupByMatr(queryWrapper, null);
        return stockGroupWarehouseMatrDTOS;
    }



    @Override
    public List<Stock> getStockListByUdi(String udi) {
        if (StringUtils.isBlank(udi)) {
            throw new BusinessException("UDI码不能为空");
        }

        // 判断唯一码类型
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("udi", udi);

        List<Stock> stockList=this.list(wrapper);

        if (stockList.size()==0) {//查找0库存
            List<StockZero> stockZerolist = stockZeroService.list(wrapper);
            if (stockZerolist.size() != 0) {

                for(StockZero stockZero:stockZerolist ){
                    Stock stock = new Stock();
                    BeanUtils.copyProperties(stockZero,stock);
                    stockList.add(stock);
                }

            }
        }

        return stockList;
    }

    @Override
    public void udiBindOrUnbind(String sn, String udi, String opType) {
        Stock stock = this.getStockByUniqueCode(sn);
        if (stock == null) {
            throw new BusinessException(String.format("在库存中未找到%s相关的耗材", sn));
        }
        if (stock.getSkuQty() <= 0) {
            throw new BusinessException("无库存");
        }
        // 判断是否已经锁定过
        StockLock stockLock = stockLockMapper.selectOne(new QueryWrapper<StockLock>().eq("stock_id", stock.getId()));

        if (stockLock != null) {
            throw new BusinessException("已存在锁定记录");
        }

        if (opType.equals("bind")) {//绑定

            if (!StringUtils.isBlank(stock.getUdi()))
                throw new BusinessException("SN【" + stock.getSn() + "】已绑定UDI【" + stock.getUdi() + "】，若需重新绑定，请先解绑");

        } else {//解绑
            if (StringUtils.isBlank(stock.getUdi()))
                throw new BusinessException("SN【" + stock.getSn() + "】未绑定UDI，无法解绑");
        }
        //更新入库单类型
        this.update(Wrappers.<Stock>update().eq("id", stock.getId())
                .set("udi", udi)
        );
    }

    /**
     * 库存效期校验
     *
     * @param sns
     * @return 库存集合
     */
    @Override
    public List<Stock> getExpStockByUC(List<String> sns) {
        if (CollectionUtils.isEmpty(sns)) {
            return null;
        }
        List<Stock> stockList = this.list(new QueryWrapper<Stock>().in("sn", sns));
        if (CollectionUtils.isEmpty(stockList)) {
            throw new BusinessException("唯一码【" + sns.get(0) + "】未找到库存记录！");
        }
        Date date = new Date();
        stockList.stream().filter(stock -> DateUtils.compareDate(stock.getExpDate(), date)).findFirst().ifPresent(stock -> {
            throw new BusinessException("该SN【%s】效期【%s】已过期", stock.getSn(), DateUtils.format(stock.getExpDate()));
        });

        return stockList;
    }

    @Override
    public Stock getExpStockByUC(String uc) {
        QueryWrapper stockQueryWrapper = getStockQueryWrapper(uc);
        stockQueryWrapper.last("limit 1");
        Stock stock = this.getOne(stockQueryWrapper, false);
        if (stock == null) {
            throw new BusinessException("唯一码【" + uc + "】未找到库存记录！");
        }
        if (stock.getSkuQty() <= 0) {
            throw new BusinessException("库存数量不足，唯一码【%s】", uc);
        }
        if (DateUtils.compareDate(stock.getExpDate(), new Date())) {
            throw new BusinessException("唯一码【%s】效期【%s】已过期", uc, DateUtils.format(stock.getExpDate()));
        }
        return stock;
    }

    @Override
    public Stock getExpStockById(String id, boolean defaultValidate) {
        Stock stock = this.getById(id);
        if (stock == null) {
            if (defaultValidate) {
                return null;
            }
            throw new BusinessException("未找到库存记录");
        }
        if (stock.getSkuQty() <= 0) {
            throw new BusinessException("库存为0");
        }
        if (DateUtils.compareDate(stock.getExpDate(), new Date())) {
            throw new BusinessException("唯一码【%s】效期【%s】已过期", stock.getSn(), DateUtils.format(stock.getExpDate()));
        }
        return stock;
    }

    @Override
    public List<Stock> getExpStockById(List<String> ids) {

        List<Stock> stockList = this.list(new QueryWrapper<Stock>().in("id", ids));
        if (CollectionUtils.isEmpty(stockList)) {
            throw new BusinessException("未找到库存记录！");
        }
        Date date = new Date();
        stockList.stream().filter(stock -> DateUtils.compareDate(stock.getExpDate(), date)).findFirst().ifPresent(stock -> {
            throw new BusinessException("该SN【%s】效期【%s】已过期", stock.getSn(), DateUtils.format(stock.getExpDate()));
        });
        return stockList;
    }

    // 二级库高值
    public String pushHisStock() {
        List<StockHisPushDTO> stockList = baseMapper.getListForHisPush();
        if (ObjectUtil.length(stockList) == 0) {
            return "推送HIS高值库存,没有可推送的数据";
        }
        long numAll = stockList.size(),numSuccess = 0, numIngoreDept = 0, numIngoreMatrCode = 0, numIngoreCategory = 0;
        numIngoreDept = stockList.stream().filter(tmp -> StringUtils.isBlank(tmp.get库房id())).count();
        numIngoreMatrCode = stockList.stream().filter(tmp -> StringUtils.isBlank(tmp.get材料编码())).count();
        numIngoreCategory = stockList.stream().filter(tmp -> StringUtils.isBlank(tmp.get耗材id())).count();
        List<StockHisPushDTO> stockListPush = stockList.stream().filter(tmp -> StringUtils.isNoneBlank(tmp.get库房id(),tmp.get材料编码(),tmp.get耗材id())).collect(Collectors.toList());
        if (stockListPush != null && stockListPush.size() > 0) {
            try {
                List<String> idSuccess = hisReqServiceImpl.pushStock(stockListPush);
                if (idSuccess != null && idSuccess.size() > 0) {
                    this.update(Wrappers.<Stock>update().set("his_pushed", GlobalConsts.YES_STR) .in("id",idSuccess));
                    numSuccess = idSuccess.size();
                }
            }catch (Exception e) {
                log.error("pushStock.error", e);
                throw  new BusinessException(e.getMessage());
            }
        }

        return StrUtil.format("推送HIS高值库存, 需推送{}, 已推送{}, 推送失败{}, 科室HIS编码为空忽略推送{}, 耗材HIS编码为空忽略推送{}, 耗材分类编码为空忽略推送{}",numAll,numSuccess,numAll-numSuccess,numIngoreDept,numIngoreMatrCode,numIngoreCategory);
    }

    // 三级库库存
    public String pushHis3Stock() {
        List<StockHisPushDTO> stockList = useDtlMapper.getListForHisPush();
        if (ObjectUtil.length(stockList) == 0) {
            return "推送HIS三级库库存,没有可推送的数据";
        }
        long numAll = stockList.size(),numSuccess = 0, numIngoreDept = 0, numIngoreMatrCode = 0, numIngoreCategory = 0;
        numIngoreDept = stockList.stream().filter(tmp -> StringUtils.isBlank(tmp.get库房id())).count();
        numIngoreMatrCode = stockList.stream().filter(tmp -> StringUtils.isBlank(tmp.get材料编码())).count();
        numIngoreCategory = stockList.stream().filter(tmp -> StringUtils.isBlank(tmp.get耗材id())).count();
        List<StockHisPushDTO> stockListPush = stockList.stream().filter(tmp -> StringUtils.isNoneBlank(tmp.get库房id(),tmp.get材料编码(),tmp.get耗材id())).collect(Collectors.toList());
        if (stockListPush != null && stockListPush.size() > 0) {
            try {
                // 填充其他字段 灭菌效期
                List<String> inLineIdList = stockListPush.stream().filter(tmp -> StringUtils.isNotBlank(tmp.getInLineId())).distinct().map(StockHisPushDTO::getInLineId).collect(Collectors.toList());
                if (!inLineIdList.isEmpty()) {
                    List<WorkOrderItem> workOrderItemList = workOrderItemMapper.selectList(Wrappers.<WorkOrderItem>query().in("id", inLineIdList));
                    if (!workOrderItemList.isEmpty()) {
                        Map<String,WorkOrderItem> workOrderItemMap = workOrderItemList.stream().collect(Collectors.toMap(o -> o.getId(), o -> o, (o1, o2) -> o1));
                        for(StockHisPushDTO hisPushDTO : stockListPush) {
                            if (workOrderItemMap.containsKey(hisPushDTO.getInLineId())) {
                                hisPushDTO.set灭菌效期(workOrderItemMap.get(hisPushDTO.getInLineId()).getSterilizationIndate());
                            }
                        }
                    }
                }
//                DynamicDataSourceContextHolder.push("dbhis");
                List<String> idSuccess = hisReqServiceImpl.pushStock(stockListPush);
//                DynamicDataSourceContextHolder.poll();
//                DynamicDataSourceContextHolder.push("master");
                if (idSuccess != null && idSuccess.size() > 0) {
                    useDtlMapper.update(null, Wrappers.<UseDtl>update().set("his_pushed", GlobalConsts.YES_STR) .in("id",idSuccess));
                    numSuccess = idSuccess.size();
                }
            }catch (Exception e) {
                log.error("pushStock.error", e);
//                DynamicDataSourceContextHolder.push("master");
                throw  new BusinessException(e.getMessage());
            }
        }

        return StrUtil.format("推送HIS三级库库存, 需推送{}, 已推送{}, 推送失败{}, 科室HIS编码为空忽略推送{}, 耗材HIS编码为空忽略推送{}, 耗材分类编码为空忽略推送{}",numAll,numSuccess,numAll-numSuccess,numIngoreDept,numIngoreMatrCode,numIngoreCategory);
    }


    @Override
    public String pushHis() {
        return this.pushHisStock() + "-----------------" + this.pushHis3Stock();
    }

    // 中联计费批量查询
    @Override
    public List<HisStockResultZhongLian> queryByUniqueCodeListFoHisZl(List<HisStockQueryZhongLian> queryList) {
        List<String> uniqueCodeList = queryList.stream().map(HisStockQueryZhongLian::getEisaiBarcode).collect(Collectors.toList());
        List<Stock> stockList = this.list(new QueryWrapper<Stock>().in("ifnull(sn,'')", uniqueCodeList).or().in("ifnull(rfid,'')", uniqueCodeList));
        if (CollectionUtils.isEmpty(stockList)) {
            throw new ValidException("未找到库存记录");
        }

        if (ObjectUtil.length(uniqueCodeList) != ObjectUtil.length(stockList)) {
            List<String> snList = stockList.stream().filter(find -> StringUtils.isNotBlank(find.getSn())).map(Stock::getSn).collect(Collectors.toList());
            List<String> rfidList = stockList.stream().filter(find -> StringUtils.isNotBlank(find.getRfid())).map(Stock::getRfid).collect(Collectors.toList());
            uniqueCodeList.stream().filter(uk -> !snList.contains(uk) && !rfidList.contains(uk)).findAny().ifPresent(snFind -> {
                throw new ValidException(snFind + "唯一码未找到相关库存，不可消耗");
            });
        }


        stockList.stream().filter(stock -> !stock.getFlagOmoc()).findAny().ifPresent(stock -> {
            throw new ValidException(stock.getSn() + "唯一码不是标签管理耗材，不可消耗");
        });

        stockList.stream().filter(stock -> stock.getPackageQty() == 0).findAny().ifPresent(stock -> {
            throw new ValidException(stock.getSn() + "库存为0,不可进行消耗操作");
        });


        List<String> matrIdList = stockList.stream().map(Stock::getMatrId).distinct().collect(Collectors.toList());

        Map<String,Matr> matrMapById = matrMapper.selectList(Wrappers.<Matr>query().in("id", matrIdList))
                .stream().collect(Collectors.toMap(Matr::getId, t -> t));
        stockList.stream().filter(stock -> !matrMapById.containsKey(stock.getMatrId())).findAny().ifPresent(stock -> {
            throw new ValidException(stock.getSn() + "未找到相关耗材,不可进行消耗操作");
        });

        stockList.stream().filter(stock -> matrMapById.get(stock.getMatrId()).getFlagDisabled()).findAny().ifPresent(stock -> {
            throw new ValidException(stock.getSn() + "相关耗材已禁用,不可进行消耗操作");
        });

        stockList.stream().filter(stock -> matrMapById.get(stock.getMatrId()).getHisDisabled()).findAny().ifPresent(stock -> {
            throw new ValidException(stock.getSn() + "相关耗材HIS已禁用,不可进行消耗操作");
        });

        Date date = new Date();
        stockList.stream().filter(stock -> DateUtils.compareDate(stock.getExpDate(), date)).findFirst().ifPresent(stock -> {
            throw new ValidException("该SN【%s】效期【%s】已过期", stock.getSn(), DateUtils.format(stock.getExpDate()));
        });

        List<String> stockIdList = stockList.stream().map(Stock::getId).distinct().collect(Collectors.toList());
        List<StockLock> locks = stockLockMapper.selectList(Wrappers.<StockLock>query().in("stock_id", stockIdList));
        if (locks != null && locks.size() > 0){
            BusinessException.throwValidFail("唯一码无法使用，已被锁定: %s",locks.get(0).getLockComment());
        }

        List<HisStockResultZhongLian> resultZhongLianList = new ArrayList<>();
        HisStockResultZhongLian resultOne;
        for(Stock stock : stockList) {
            resultOne = new HisStockResultZhongLian();
            // 材料id
            resultOne.setEisaiItemId(stock.getMatrId());
            // 材料规格
            resultOne.setEisaiItemName(stock.getMatrSpec());
            // 产地
            resultOne.setEisaiItemDprentpName(stock.getMfgName());
            // 成本价
            resultOne.setEisaiItemCostPrice(stock.getSkuPrice());
            // 零售价
            resultOne.setEisaiItemSalesPrice(stock.getSkuPrice());
            // 库房id
            resultOne.setEisaiItemStoreId(stock.getWarehouseId());
            // 库存量
            resultOne.setEisaiItemStoreQunt(stock.getSkuQty());
            // 条码
            resultOne.setEisaiBarcode(stock.getSn());
            resultZhongLianList.add(resultOne);
        }

        return resultZhongLianList;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String excelImportForImportStock(MultipartFile file, Map<String, String> reqData) {
        List<Stock> itemImportList = excelGetDataList(file,reqData, ExcelImportBaseDataConfig.getImportStock());
        return SingleService.inst.inOrderService.createByStockImport(itemImportList);
    }

}
